package com.zr.utils;

import java.io.IOException;
import java.util.*;

/**
 * @author 杜雨萌
 * @date 2022/10/29
 * @version 2022.1
 */
public class WeightAllocationUtil {

    /**
     * 计算各条路径的权重
     *
     * @param cityList
     * @return 权重二维数组
     * @author 杜雨萌
     */
    public static double[][] weightAllocation(List<String> cityList) throws IOException {
        //城市列表转为数组
        String[] cities = cityList.toArray((new String[cityList.size()]));
        //得到距离权重矩阵
        double[][] distanceMatrix = weightDistance(cities);
        //获得疫情严重城市列表
        List<String> dangerCityList = isHighDanger(cities);
        //计算权重矩阵(当前只有距离，增加成本会改变权重矩阵)
        double[][] weightMatrix = distanceMatrix;
        //判断疫情城市，形成最后结果矩阵
        double[][] resultMatrix = getResultMatrix(weightMatrix, dangerCityList, cityList);
        //
        seeResultMatrix(resultMatrix);
        return resultMatrix;
    }

    /**
     * 计算距离权重
     *
     * @param cities
     * @return
     * @author 杜雨萌
     */
    public static double[][] weightDistance(String[] cities) {
        // 定义一个距离矩阵
        double[][] distance = new double[cities.length][cities.length];
        //将所有城市之间的距离放入到数组中
        for (int i = 0; i < distance.length; i++) {
            //当前城市到其他城市之间的权重数组
            double[] temp = new double[cities.length];
            for (int j = 0; j < distance.length; j++) {
                //判断城市是否测试自己的距离，返回是1，强行改为0
                if (cities[i].equals(cities[j])) {
                    temp[j] = 0;
                } else {
                    //添加距离到数组中
                    temp[j] = LngAndLatUtil.getDistance(cities[i], cities[j]).get("distance");
                }
            }
            distance[i] = temp;
        }
        //对数组进行归一化
        double[][] distanceNormalize = NormalizeUtil.getNormalize(distance);
        //w为距离权重
        int w = 10;
        //将数组所有数据乘上距离权重
        for (int i = 0; i < distanceNormalize.length; i++) {
            for (int j = 0; j < distanceNormalize[i].length; j++) {
                int[][] result = new int[distanceNormalize.length][distanceNormalize.length];
                result[i][j] = (int) (w * distanceNormalize[i][j]);
            }
        }
        return distanceNormalize;
    }

    /**
     * 得到高风险城市疫情情况
     *
     * @param cities
     * @return
     * @throws IOException
     * @author 杜雨萌
     */
    public static List<String> isHighDanger(String[] cities) throws IOException {
        List<String> dangerCityList = new ArrayList<>();
        //所有城市判断是否是高风险城市，如果是传入高风险城市列表
        for (int i = 0; i < cities.length; i++) {
            Map<String, Object> temp = new HashMap<>();
            temp = EpidemicSituationUtil.getTransCityData(cities[i]);
            if (temp.get("isSpecialCity") != null && temp.get("isSpecialCity").equals("true")) {
                dangerCityList.add(cities[i]);
            }
        }
        return dangerCityList;
    }

    /**
     * 根据疫情城市列表，更新每个城市到疫情城市的权重，将权重设为最大值，并将疫情城市到自己城市赋值为0
     *
     * @param weightMatrix
     * @param dangerCityList
     * @param cityList
     * @return
     */
    public static double[][] getResultMatrix(double[][] weightMatrix, List<String> dangerCityList, List<String> cityList) {
        //计算最终权重二维数组
        double[][] resultMatrix = weightMatrix;
        //循环遍历所有的高风险城市
        for (int k = 0; k < dangerCityList.size(); k++) {
            //如果城市list中包含高风险城市，将城市的权重设为无限大
            if (cityList.contains(dangerCityList.get(k))) {
                //index是高风险城市在citylist中的索引
                int index = cityList.indexOf(dangerCityList.get(k));
                for (int i = 0; i < resultMatrix.length; i++) {
                    for (int j = 0; j < resultMatrix.length; j++) {
                        //如果是结果矩阵中的第j列和疫情城市对应的index列相等
                        if (j == index) {
                            //将权重设为无限大
                            resultMatrix[i][j] = Integer.MAX_VALUE;
                        }
                        //疫情城市到自己也会变为无限大，需要将疫情城市到自己设为0
                        if (i == j) {
                            resultMatrix[i][j] = 0;
                        }
                    }
                }
            }
        }
        return resultMatrix;
    }

    /**
     * 查看权重结果集
     *
     * @param resultMatrix
     * @author 杜雨萌
     */
    public static void seeResultMatrix(double[][] resultMatrix) {
        for (int i = 0; i < resultMatrix.length; i++) {
            for (int j = 0; j < resultMatrix[i].length; j++) {
                System.out.print(resultMatrix[i][j] + "                ");
            }
            System.out.println("");
        }
    }
}
